﻿//#define Normal
//#define Border1
#define Border2

using System;
using System. Linq;
using System. Net;
using System. Windows;
using System. Windows. Controls;
using System. Windows. Data;
using System. Xml. Linq;
using Microsoft. Phone. Controls;
using Microsoft. Phone. Shell;
using NextApp. WP7. AppConfig;
using NextApp. WP7. Models;
using NextApp. WP7. UnionLib;
using WP7_ControlsLib. Controls;
using System. Collections. ObjectModel;
using NextApp. WP7. Cache. NextApp;

namespace NextApp. WP7. View. Controls
{
    public partial class PostsList : UserControl
    {
        #region Initialize
        public PostsList( )
        {
            InitializeComponent( );
			//检测显示模板
			this. CheckPostListTemplate( );
			//
			this. Loaded += new RoutedEventHandler(PostsList_Loaded);
			this. postsBinding = new ObservableCollection<object>( );
			this. postsBinding. Add(this. loadNextTip); 
			this. list_Posts. ItemsSource = this. postsBinding;
			this. loadNextTip. Click += (s, e) =>
				{
					this. LoadNextPosts( );
				};
			//滚动检测
			this. list_Posts. LayoutUpdated += new EventHandler(list_Posts_LayoutUpdated);
			//加载数据
			this. Reload( );

			EventSingleton. Instance. OnChangedPostListLayout += new EventHandler<TagEventArgs>(Instance_OnChangedPostListLayout);
        }

		void Instance_OnChangedPostListLayout(object sender, TagEventArgs e)
		{
			PostListLayoutType type = ( PostListLayoutType )e. Tag;
			switch ( type )
			{
				case PostListLayoutType. Normal:
					this. list_Posts. ItemTemplate = this. Resources[ "template_Normal" ] as DataTemplate;
					break;
				case PostListLayoutType. Border1:
					this. list_Posts. ItemTemplate = this. Resources[ "template_Border1" ] as DataTemplate;
					break;
				case PostListLayoutType. Border2:
					this. list_Posts. ItemTemplate = this. Resources[ "template_Border2" ] as DataTemplate;
					break;
			}
			if ( this. postsBinding != null )
			{
				for ( int i = 0 ; i < postsBinding. Count - 1 ; i++ )
				{
					postsBinding. RemoveAt(i--);
				}
				this. fromPost = 0;
				this. Reload(false);
			}
		}
		void CheckPostListTemplate( )
		{
			switch ( Config.Instance.PostListLayoutType )
			{
				case PostListLayoutType. Normal:
					this. list_Posts. ItemTemplate = this. Resources[ "template_Normal" ] as DataTemplate;
					break;
				case PostListLayoutType. Border1:
					this. list_Posts. ItemTemplate = this. Resources[ "template_Border1" ] as DataTemplate;
					break;
				case PostListLayoutType. Border2:
					this. list_Posts. ItemTemplate = this. Resources[ "template_Border2" ] as DataTemplate;
					break;
			}
		}
		private LoadNextTip loadNextTip = new LoadNextTip
		{
			Text = "正在刷新",
			HorizontalAlignment = HorizontalAlignment. Center,
			HorizontalContentAlignment = HorizontalAlignment. Center,
			Width = 480,
			MinWidth = 480,
			Height = 100,
			MinHeight = 100,
		};
        private const int fetchCount = 5;
        private int fromPost = 0;
        public int catalogID { get; set; }
        public bool IsHostByMainPage { get; set; }
        private bool IsLoadingData { get; set; }
		public ObservableCollection<object> postsBinding { get; private set; }
		private ScrollViewer listBox_ScrollViewer;
		private double lastListBoxScrollableVerticalOffset = 0;
		#endregion

		#region 刷新/载入文章列表
		private void list_Posts_LayoutUpdated(object sender, EventArgs e)
		{
			if ( this. listBox_ScrollViewer != null )
			{
				//是否往下滑动
				bool isGoingDown = this. listBox_ScrollViewer. VerticalOffset > lastListBoxScrollableVerticalOffset;
				this. lastListBoxScrollableVerticalOffset = this. listBox_ScrollViewer. VerticalOffset;
				//是否在监控的最底部区域
				bool isInReloadRegion = this. listBox_ScrollViewer. VerticalOffset >= ( this. listBox_ScrollViewer. ScrollableHeight - Config. ScrollBarOffset );
				if ( isInReloadRegion &&
					isGoingDown  )
				{
					this. LoadNextPosts( );
				}
			}
			else
			{
				this. listBox_ScrollViewer = ControlHelper. FindChildOfType<ScrollViewer>(this. list_Posts);
			}
		}
		private void LoadNextPosts( )
		{
			if ( this. IsLoadingData )
			{
				System. Diagnostics. Debug. WriteLine("文章刷新中 无法重新获取");
				return;
			}
			if ( this. postsBinding. IsNotNullOrEmpty( ) && this. postsBinding. Count >= 2 )
			{
				Post lastPost = this. postsBinding[ this. postsBinding. Count - 2 ] as Post;
				if ( lastPost != null )
				{
					this. fromPost = lastPost. id;
					this. Reload(false);
				}
			}
		}
        public void Reload( bool isInitialize = true, int from = -1, bool isClearItemSource = false )
        {
            //是否需要清空 ListBox 的缓存
            if ( isClearItemSource )
            {
				this. postsBinding. Clear( );
				this. postsBinding. Add(this. loadNextTip);
				this. loadNextTip. Text = "正在刷新";
            }
			string url = Config. Instance. GetApi(string. Format("{0}&catalog={1}&fromPost={2}&fetchCount={3}&guid={4}",
																					NextAppSingleton. Instance. url_post_list,
																					this. catalogID,
																					from < 0 ? this. fromPost : from,
																					fetchCount,
																					Guid. NewGuid( )));
            //判断是否可从缓存中获取数据
			if ( this. CheckIsCached(from) )
			{
				//入队操作
				CacheNextApp. Instance. Enqueue(new AsyncMissionNextApp
				{
					queryStringWithUrl = url,
					 Type = AsyncMissionNextAppType.Post_List,
				});
			}
			else
			{
				//开始获取
				WebClient client = new WebClient( );
				client. Headers[ "User-Agent" ] = Config. Instance. Http_User_Agent;
				client. DownloadStringCompleted += (s, e1) =>
				{
					#region 错误处理
					if ( e1. Error != null )
					{
						MessageBox. Show("获取此分类下的文章列表失败", "网络错误", MessageBoxButton. OK);
						return;
					}
					#endregion

					#region 获取到了数据
					XElement x;
					try
					{
						x = XElement. Parse(e1. Result);
					}
					catch ( Exception )
					{
						return;
					}
					PostList postList = new PostList
					{
						catalog = x. Element("catalog"). Value. ToInt32( ),
						postCount = x. Element("postCount"). Value. ToInt32( ),
						posts = x. Element("posts") == null ?
							null :
							x. Element("posts"). Elements("post"). Select(
							p => new Post
							{
								id = p. Element("id"). Value. ToInt32( ),
								title = p. Element("title"). Value,
								outline = p. Element("outline"). Value,
								commentCount = p. Element("commentCount"). Value. ToInt32( ),
								authorId = p. Element("authorId"). Value. ToInt32( ),
								author = p. Element("author"). Value,
								catalog = p. Element("catalog"). Value. Split(','). Select(c => c. ToInt32( )). ToArray( ),
								pubDate = p. Element("pubDate"). Value,
								img = p. Element("img") == null ? null : p. Element("img"). Value,
							}
						). ToArray( ),
					};
					#endregion

					#region 如果获取到了新文章列表
					if ( postList. posts != null )
					{
						this. loadNextTip. Text = "更多 . . .";
						//存储到缓存
						CacheNextApp. Instance. SavePostListToCache(postList. posts);
						//获取已有的文章的 id 集合
						int[ ] postIDS = GetCurrentPostsIDS;
						//然后插入数据  需要判断重复性
						postList. posts = postList. posts. Where(p => postIDS. Contains(p. id) == false). ToArray( );
						postList. posts. ForAll(p => this. postsBinding. Insert(this. postsBinding. Count - 1, p));
						//智能 预估计刷新页面
						if ( postList.posts.Length > 0 )
						{
							CacheNextApp. Instance. Enqueue(new AsyncMissionNextApp
							{
								 Type = AsyncMissionNextAppType.Post_List,
								queryStringWithUrl = Config. Instance. GetApi(string. Format("{0}&catalog={1}&fromPost={2}&fetchCount={3}&guid={4}",
																												   NextAppSingleton. Instance. url_post_list,
																												   this. catalogID,
																												   postList. posts. LastOrDefault( ). id,
																												   fetchCount,
																												   Guid. NewGuid( ))),
							});
						}
						//将没有文章的提示关闭显示
						this. tblock_NoPostsTip. Visibility = System. Windows. Visibility. Collapsed;
						//执行后台搜索
						this. NotifyStartToPollNewBlogs( );
					}
					#endregion

					#region 如果这次没有获取新文章列表
					else
					{
						if ( isInitialize && this. list_Posts. Items. Count <= 0 )
						{
							this. tblock_NoPostsTip. Text = "没有文章";
							this. tblock_NoPostsTip. Visibility = System. Windows. Visibility. Visible;
						}
						else
						{
							this. loadNextTip. Text = "已经没有最新文章";
						}
					}
					#endregion
					//通知 MainPage
					this. IsDisplayProgressBar(false);
				};
				#region 异步http 加载
				if ( NextAppSingleton. Instance. url_post_list. IsNotNullOrWhitespace( ) )
				{
					client. DownloadStringAsync(new Uri(url, UriKind. Absolute));
					//展示进度条
					this. IsDisplayProgressBar(true);
				}
				#endregion
			}
		}
        private bool CheckIsCached( int from )
        {
			Post[ ] posts = CacheNextApp. Instance. GetPostListFromCache(catalogID, from < 0 ? fromPost : from, fetchCount);
			if ( posts != null && posts. Length > 0 )
			{
				this. loadNextTip. Text = "更多 . . .";
				//首先获取文章列表的ID集合
				int[ ] postsIDS = this. GetCurrentPostsIDS;
				//然后插入数据 这里需要判断重复性
				posts = posts. Where(p => postsIDS. Contains(p. id) == false). ToArray( );
				if ( posts.Length <= 0 && fromPost > 0)
				{
					return false;
				}
				posts. ForAll(p => this. postsBinding. Insert(this. postsBinding. Count - 1, p));
				
				return true;
			}
			else
			{
				return false;
			}
        }
		private int[ ] GetCurrentPostsIDS
		{
			get
			{
				int[ ] postIDS = this. postsBinding. Select(p =>
				{
					Post tempP = p as Post;
					return tempP == null ? -1 : tempP. id;
				}). ToArray( );
				return postIDS;
			}
		}

        #endregion

        #region 点击某篇文章
        private void list_Posts_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            Post p = this. list_Posts. SelectedItem as Post;
            this. list_Posts. SelectedItem = null;
            //跳转
            if ( p != null )
            {
                ( Application. Current. RootVisual as PhoneApplicationFrame ). Navigate(new Uri(string. Format("/View/PostDetail.xaml?post={0}", p. id), UriKind. Relative));
            }
        }
        #endregion

        #region 进度条设置
		private void IsDisplayProgressBar(bool visible)
		{
			if ( this. IsHostByMainPage )
			{
				EventSingleton. Instance. RaiseOnMainPageLoading(visible);
			}
			else
			{
				this. ProgressIndicatorIsVisible = visible;
			}
			//加载指示器
			this. IsLoadingData = visible;
		}
        private void PostsList_Loaded(object sender, RoutedEventArgs e)
        {
			SystemTray. ProgressIndicator = new ProgressIndicator( );
			SystemTray. ProgressIndicator. Text = "加载中";

            Binding bindingData;
            bindingData = new Binding("ProgressIndicatorIsVisible");
            bindingData. Source = this;
            BindingOperations. SetBinding(SystemTray. ProgressIndicator, ProgressIndicator. IsVisibleProperty, bindingData);
            BindingOperations. SetBinding(SystemTray. ProgressIndicator, ProgressIndicator. IsIndeterminateProperty, bindingData);
        }
        public static readonly DependencyProperty ProgressIndicatorIsVisibleProperty =
            DependencyProperty. Register("ProgressIndicatorIsVisible",
            typeof(bool),
            typeof(PostsList),
            new PropertyMetadata(false));
        public bool ProgressIndicatorIsVisible
        {
            get { return ( bool )GetValue(ProgressIndicatorIsVisibleProperty); }
            set { SetValue(ProgressIndicatorIsVisibleProperty, value); }
        }
        #endregion

        #region 将某篇文章订到桌面上
        private void menuItem_PostPinToStart_Click(object sender, RoutedEventArgs e)
        {
            Post p = ( sender as MenuItem ). DataContext as Post;
            if ( p != null )
            {
                Util. Tool. CreateShellTile(p);
            }
        }
        #endregion

        #region 获取文章列表后通知开始轮询后台搜索
        private void NotifyStartToPollNewBlogs( )
        {
            if ( this.catalogID == 0 )
            {
                Post lastP = this. list_Posts. Items. LastOrDefault( ) as Post;
                if ( lastP != null )
                {
                    EventSingleton. Instance. RaiseOnGetPosts(new RenewBlogs
                    {
                        Duration = Config. Instance. TimeSpan_Polling,
                        LastPostID = lastP. id,
                        title = Config. Instance. blog_title,
                        Uri = Config. Instance. GetApi(string. Format("{0}&catalog=0&fromPost={1}&fetchCount=99", NextAppSingleton. Instance. url_post_list, lastP. id)),
                        UserAgent = Config. Instance. Http_User_Agent,
                    });
                }
            }
        }
        #endregion

		#region 删除文章
		private void menuItem_PostDelete_Click(object sender, RoutedEventArgs e)
		{
			if ( Config. Instance. IsLogin == false )
			{
				if ( MessageBox. Show("请先登录才能删除文章", "请登陆", MessageBoxButton. OKCancel) == MessageBoxResult. OK )
				{
					Util. Tool. Login( );
					return;
				}
			}
			else
			{
				Post p = ( sender as MenuItem ). DataContext as Post;
				if ( p != null )
				{
					this. DeletePost(p. id);
				}
			}
		}
		private void DeletePost(int id)
		{
			WebClient client = new WebClient( );
			client. Headers[ "User-Agent" ] = Config. Instance. Http_User_Agent;
			client. DownloadStringCompleted += (s, e1) =>
			{
				if ( e1. Error != null )
				{
					System. Diagnostics. Debug. WriteLine("删除文章失败: {0}", e1. Error. Message);
					return;
				}
				XElement osmobile;
				try
				{
					osmobile = XElement. Parse(e1. Result);
				}
				catch ( Exception )
				{
					return;
				}
				ApiError _error = new ApiError
				{
					errorCode = osmobile. Element("result"). Element("errorCode"). Value. ToInt32( ),
					errorMessage = osmobile. Element("result"). Element("errorMessage"). Value,
				};
				//隐藏进度条
				this. IsDisplayProgressBar(false);
				//显示删除结果 如果删除成功 则清空该类型评论的缓存以及通知刷新评论
				if ( this. DisplayResult_DeletePost(_error) )
				{
					this. postsBinding. Remove(this. postsBinding. FirstOrDefault(p =>
					{
						Post _p = p as Post;
						if ( _p != null )
							return _p. id == id;
						else
							return false;
					}));
				}
			};
			client. Headers[ "Cookie" ] = Config. Instance. Cookie;
			if ( NextAppSingleton. Instance. url_comment_delete. IsNotNullOrWhitespace( ) )
			{
				client. DownloadStringAsync(new Uri(Config. Instance. GetApi(string. Format("{0}&post={1}", NextAppSingleton.Instance.url_post_delete, id)),
																UriKind. Absolute));
				//显示进度条
				this. IsDisplayProgressBar(true);
			}
		}
		private bool DisplayResult_DeletePost(ApiError error)
		{
			switch ( error. errorCode )
			{
				case 1:
					MessageBox. Show("文章删除成功");
					return true;
				case 0:
					MessageBox. Show("对不起, 用户未登录, 无法删除");
					return false;
				case -1:
					MessageBox. Show("对不起, 无法删除, 其他错误");
					return false;
				case -2:
					MessageBox. Show("对不起, 您没有删除文章的权限");
					return false;
			}
			return false;
		}
		#endregion
	}
}
